package com.neusoft.neuiotms.dcam.workflow.service.impl;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

import javax.persistence.EntityNotFoundException;
import javax.transaction.Transactional;

import org.activiti.engine.TaskService;
import org.activiti.engine.task.Task;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import com.neusoft.bizcore.activiti.constants.BizcoreActivitiConstants;
import com.neusoft.bizcore.activiti.dto.ProcessInstanceDTO;
import com.neusoft.bizcore.activiti.service.ProcessInstanceService;
import com.neusoft.bizcore.activiti.service.WorkOrderService;
import com.neusoft.bizcore.auth.common.bean.UserBean;
import com.neusoft.bizcore.web.constant.ExceptionConstants;
import com.neusoft.bizcore.web.dto.result.ResultListDTO;
import com.neusoft.bizcore.web.exception.UnitedException;
import com.neusoft.neuiotms.common.constant.AHConstants;
import com.neusoft.neuiotms.dcam.constant.DCAMConsts;
import com.neusoft.neuiotms.dcam.fixed.dto.AssetLifeCycleDTO;
import com.neusoft.neuiotms.dcam.fixed.model.Asset;
import com.neusoft.neuiotms.dcam.fixed.repository.AssetRepository;
import com.neusoft.neuiotms.dcam.fixed.service.AssetLifeCycleService;
import com.neusoft.neuiotms.dcam.fixed.service.AssetService;
import com.neusoft.neuiotms.dcam.workflow.converter.DiaoboSLConverter;
import com.neusoft.neuiotms.dcam.workflow.dto.ConfirmSLDTO;
import com.neusoft.neuiotms.dcam.workflow.dto.DiaoboSLDTO;
import com.neusoft.neuiotms.dcam.workflow.model.DiaoboItemSL;
import com.neusoft.neuiotms.dcam.workflow.model.DiaoboSL;
import com.neusoft.neuiotms.dcam.workflow.repository.DiaoboItemSLRepository;
import com.neusoft.neuiotms.dcam.workflow.repository.DiaoboSLRepository;
import com.neusoft.neuiotms.dcam.workflow.service.ConfirmSLService;
import com.neusoft.neuiotms.dcam.workflow.service.DiaoboSLService;
import com.neusoft.neuiotms.micro.auth.AuthMicroService;

import io.micrometer.core.instrument.util.StringUtils;

@Service
public class DiaoboSLServiceImpl implements DiaoboSLService {

    @Autowired
    private WorkOrderService workOrderService;
    @Autowired
    private ProcessInstanceService processInstanceService;
    @Autowired
    private DiaoboSLRepository diaoboSLRepository;
    @Autowired
    private DiaoboSLConverter diaoboSLConverter;
    @Autowired
    private DiaoboItemSLRepository diaoboItemSLRepository;
    @Autowired
    private AssetRepository assetRepository;
    @Autowired
    private AssetService assetService;
    @Autowired
    private AuthMicroService authMicroService;
    @Autowired
    private AssetLifeCycleService assetLifeCycleService;
    @Autowired
    private TaskService taskService;
    @Autowired
    private ConfirmSLService confirmSLService;

    @Override
    @Transactional
    public DiaoboSLDTO create(final DiaoboSLDTO dto, final UserBean user) {

        final String taskId = dto.getTaskId();
        final ProcessInstanceDTO instance =
                this.workOrderService.submit(dto.getTitle(), DCAMConsts.PROCESSS_DIAOBO_SL_KEY, dto.getWorkOrderNum(),
                        user);
        dto.setTaskId(instance.getTaskId());
        dto.setWorkOrderNum(instance.getWorkorderNum());
        dto.setCreateUser(user.getUsername());
        dto.setCreateUserName(user.getName());

        // 查询当前workOrderNum和TaskId下是否存在记录
        final DiaoboSL oldModel = this.diaoboSLRepository.findByWorkOrderNumAndTaskId(
                dto.getWorkOrderNum(), taskId);
        if (oldModel == null) {
            dto.setId(null);
        }

        // 解锁以前的资产信息
        final List<DiaoboItemSL> all = this.diaoboItemSLRepository.findByMain_WorkOrderNum(dto.getWorkOrderNum());
        if (null != all) {
            this.assetService.updateLocked(all.stream().map(l -> l.getCode()).distinct().collect(Collectors.toList()),
                    false);
        }

        DiaoboSL model = this.diaoboSLConverter.toModel(dto);
        model = this.diaoboSLRepository.save(model);

        // 枷锁资产信息
        this.assetService.updateLocked(
                model.getDetails().stream().map(l -> l.getCode()).distinct().collect(Collectors.toList()),
                true);

        // 转入部门资产管理员
        final List<String> users = new ArrayList<>();
        final Map<String, Object> search = new HashMap<>();
        search.put("s_orgCode", dto.getDestManagementOrgCode());
        search.put("s_roleCode", AHConstants.ROLE_SL_DEPT_ASSET_ADMIN);
        final ResultListDTO<Map<String, Object>> userList = this.authMicroService.userIndex(search);
        userList.getData().stream().map(l -> l.get("username").toString()).filter(s -> null != s)
                .forEach(users::add);

        if (users.isEmpty()) {
            throw new UnitedException(dto.getDestManagementOrgName() + "部门资产管理员不存在,联系系统管理员");
        }

        this.processInstanceService.setGlobalVariable(dto.getTaskId(), DCAMConsts.PROCESSS_DISPATCHUSERLIST,
                users);

        // 更新资产状态为转移中
        final List<String> codes = dto.getDetails().stream().map(l -> l.getCode()).distinct()
                .collect(Collectors.toList());
        this.assetService.updateStatus(codes, DCAMConsts.ASSET_STATUS_TRANSFER);

        // 完成当前节点
        this.processInstanceService.complete(dto.getWorkOrderNum(), dto.getTaskId(), user);
        return this.diaoboSLConverter.toDTO(model);
    }

    @Override
    public DiaoboSLDTO detail(final String workOrderNum, final String taskId, final UserBean user) {
        DiaoboSL model = null;
        try {
            if (StringUtils.isNotBlank(workOrderNum) && !"NULL".equals(taskId)) {
                model = this.diaoboSLRepository.findByWorkOrderNumAndTaskId(workOrderNum, taskId);
                if (model == null) {
                    // 获取前一节点的TaskID
                    final String lastTaskId = this.processInstanceService.getLastTaskId(taskId, user);
                    if (lastTaskId == null) {
                        return new DiaoboSLDTO();
                    } else {
                        model = this.diaoboSLRepository.findByWorkOrderNumAndTaskId(workOrderNum,
                                lastTaskId);
                    }
                }
            } else if ("NULL".equals(taskId)) {
                model =
                        this.diaoboSLRepository.findTopByWorkOrderNumOrderByCreateTimeDesc(workOrderNum);
            }
        } catch (final EntityNotFoundException e) {
            throw new UnitedException(ExceptionConstants.ENTITY_NOT_FOUND,
                    new Object[] {workOrderNum },
                    new Object[] {taskId });
        }
        return this.diaoboSLConverter.toDTO(model);
    }

    @Transactional
    @Override
    public void confirmCreate(final DiaoboSLDTO dto, final UserBean user) {

        final DiaoboSL model =
                this.diaoboSLRepository.findTopByWorkOrderNumOrderByCreateTimeDesc(dto.getWorkOrderNum());

        // 修改位置信息
        dto.getDetails().forEach(l -> {
            model.getDetails().forEach(s -> {
                if (l.getId().toString().equals(s.getId().toString())) {
                    s.setDiaoboLocation(l.getDiaoboLocation());
                    s.setDiaoboLocationName(l.getDiaoboLocationName());
                    s.setDiaoboUser(l.getDiaoboUser());
                    s.setDiaoboUserName(l.getDiaoboUserName());
                }
            });
        });

        if (model.getDetails().size() > 0) {
            this.diaoboItemSLRepository.saveAll(model.getDetails());
        }

        //        this.diaoboSLCompleteUpdate(dto);
        this.processInstanceService.setGlobalVariable(dto.getTaskId(),
                "passFlag", true);
        this.processInstanceService.complete(dto.getWorkOrderNum(), dto.getTaskId(), user);

        this.confirmSLService.create(ConfirmSLDTO.builder().workOrderNum(dto.getWorkOrderNum()).taskId(dto.getTaskId())
                .createUser(user.getUsername()).createUserName(user.getName()).mainId(model.getId()).build());
    }

    @Override
    public DiaoboSLDTO confirmDetails(final String workOrderNum, final String taskId, final UserBean user) {
        DiaoboSL model = null;
        Long mainId = null;
        try {
            if (StringUtils.isNotBlank(workOrderNum) && !"NULL".equals(taskId)) {

                mainId = this.confirmSLService.getMainId(workOrderNum, taskId);
                if (mainId == null) {
                    // 获取前一节点的TaskID
                    final String lastTaskId = this.processInstanceService.getLastTaskId(taskId, user);
                    if (lastTaskId == null) {
                        model =
                                this.diaoboSLRepository.findTopByWorkOrderNumOrderByCreateTimeDesc(workOrderNum);
                    } else {
                        mainId = this.confirmSLService.getMainId(workOrderNum, lastTaskId);
                        model = this.diaoboSLRepository.getOne(mainId);
                    }
                } else {
                    model = this.diaoboSLRepository.getOne(mainId);
                }
            } else if ("NULL".equals(taskId)) {
                model = this.diaoboSLRepository.findTopByWorkOrderNumOrderByCreateTimeDesc(workOrderNum);
            }
        } catch (final EntityNotFoundException e) {
            throw new UnitedException(ExceptionConstants.ENTITY_NOT_FOUND,
                    new Object[] {workOrderNum },
                    new Object[] {taskId });
        }
        return this.diaoboSLConverter.toDTO(model);
    }

    @Override
    public void processEnd(final String workOrderNum) {

        final String instanceId = this.workOrderService.getInstanceIdByWorkorderNum(workOrderNum);
        if (instanceId == null) {
            throw new UnitedException(BizcoreActivitiConstants.PROCESS_EXIST);
        }

        final List<Task> task = this.taskService.createTaskQuery().processInstanceId(instanceId).list();
        if (task.isEmpty()) {
            final DiaoboSL model = this.diaoboSLRepository.findTopByWorkOrderNumOrderByCreateTimeDesc(workOrderNum);
            this.diaoboSLCompleteUpdate(this.diaoboSLConverter.toDTO(model));
        }

    }

    private void diaoboSLCompleteUpdate(final DiaoboSLDTO dto) {
        final List<String> codes = dto.getDetails().stream().map(l -> l.getCode()).distinct()
                .collect(Collectors.toList());

        final List<AssetLifeCycleDTO> lifeList = new ArrayList<>();

        if ((codes != null) && (codes.size() > 0)) {
            final List<Asset> assets = this.assetRepository.findByCodeIn(codes);
            // 修改位置
            dto.getDetails().forEach(l -> {
                assets.forEach(s -> {
                    if (l.getCode().equals(s.getCode())) {
                        s.setLocation(l.getDiaoboLocation());
                        s.setLocationName(l.getDiaoboLocationName());
                        s.setManagementUserCode(l.getDiaoboUser());
                        s.setManagementUserName(l.getDiaoboUserName());
                        s.setManagementOrgCode(dto.getDestManagementOrgCode());
                        s.setManagementOrgName(dto.getDestManagementOrgName());
                        s.setLocked(false);
                        s.setStatus(DCAMConsts.ASSET_STATUS_USED);

                        // 生命周期
                        lifeList.add(AssetLifeCycleDTO.builder().code(l.getCode())
                                .lifeCycle(DCAMConsts.ASSET_LIFE_TYPE_DIAOBO)
                                .content(l.getName() + "已经被调拨到" + dto.getDestManagementOrgName() + "部门")
                                .workNum(dto.getWorkOrderNum()).build());
                    }
                });
            });

            this.assetRepository.saveAll(assets);

            if (lifeList.size() > 0) {
                this.assetLifeCycleService.batchCreate(lifeList);
            }
        }
    }

}
